import asyncio
import logging
import os
import sys
from loguru import logger
from pathlib import Path
from types import FrameType
from typing import cast

from application.config import appSettings as settings


class InterceptHandler(logging.Handler):
    """
    日志拦截处理器：将所有 Python 标准日志重定向到 Loguru

    工作原理：
    1. 继承自 logging.Handler
    2. 重写 emit 方法处理日志记录
    3. 将标准库日志转换为 Loguru 格式
    """
    def emit(self, record: logging.LogRecord) -> None:  # pragma: no cover
        # Get corresponding Loguru level if it exists
        try:
            level = logger.level(record.levelname).name
        except ValueError:
            level = str(record.levelno)

        # Find caller from where originated the logged message
        frame, depth = logging.currentframe(), 2
        while frame.f_code.co_filename == logging.__file__:  # noqa: WPS609
            frame = cast(FrameType, frame.f_back)
            depth += 1

        logger.opt(depth=depth, exception=record.exc_info).log(
            level, record.getMessage(),
        )


async def setup_logging():
    """
    配置日志系统

    功能：
    1. 控制台彩色输出
    2. 文件日志轮转
    3. 错误日志单独存储
    4. 异步日志记录
    """
    # 步骤1：移除默认处理器
    logger.remove()

    # 步骤2：定义日志格式
    log_format = (
        # 时间信息
        "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | "
        # 日志级别，居中对齐
        "<level>{level: ^8}</level> | "
        # 进程和线程信息
        "process [<cyan>{process.name}</cyan>]:<cyan>{thread.name}</cyan> | "
        # 文件、函数和行号
        "<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - "
        # 日志消息
        "<level>{message}</level>"
    )

    # 步骤3：配置控制台输出
    logger.add(
        sys.stdout,
        format=log_format,
        level=logging.DEBUG if settings.app_debug else logging.INFO,
        enqueue=True,        # 启用异步写入
        backtrace=True,      # 显示完整的异常回溯
        diagnose=True,       # 显示变量值等诊断信息
        colorize=True        # 启用彩色输出
    )

    # 步骤4：创建日志目录
    log_dir = Path(settings.log_path) / 'web'
    if not os.path.exists(log_dir):
        os.makedirs(str(log_dir), exist_ok=True)

    # 步骤5：配置常规日志文件
    logger.add(
        str(log_dir / "{time:YYYY-MM-DD}.log"),
        format=log_format,
        level=logging.INFO,
        rotation=settings.log_rotation,    # 每天轮转
        retention=settings.log_retention,  # 保留30天
        compression=settings.log_compression,  # 压缩旧日志
        encoding="utf-8",
        enqueue=True                      # 异步写入
    )

    # 步骤6：配置错误日志文件
    logger.add(
        str(log_dir / "error_{time:YYYY-MM-DD}.log"),
        format=log_format,
        level=logging.ERROR,
        rotation=settings.log_rotation,
        retention=settings.log_retention,
        compression=settings.log_compression,
        encoding="utf-8",
        enqueue=True
    )

    # 步骤7：配置标准库日志
    logging.basicConfig(handlers=[InterceptHandler()], level=0, force=True)

    # 步骤8：配置第三方库日志
    logger_names = [
        "uvicorn",
        "uvicorn.error",
        "uvicorn.access",
        "uvicorn.asgi",
        "fastapi",
        "fastapi.error",
        # 自定义日志器
        "sanren",
        "abolish",
        "order.gen.job",
    ]
    logging.getLogger().handlers = [InterceptHandler()]
    for logger_name in logger_names:
        _logger = logging.getLogger(logger_name)
        _logger.handlers = [InterceptHandler()]
        _logger.setLevel(logging.DEBUG if settings.app_debug else logging.INFO)
        _logger.propagate = False

    logger.info("日志系统初始化完成")


__all__ = ['setup_logging']
